home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / NR3.C < prev    next >
Text File  |  1993-08-09  |  29KB  |  1,077 lines

  1. /* net/rom level 3 low level processing
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include "global.h"
  9. #include "config.h"
  10. #ifdef NETROM
  11. #include "mbuf.h"
  12. #include "pktdrvr.h"
  13. #include "iface.h"
  14. #include "netuser.h"
  15. #include "timer.h"
  16. #include "arp.h"
  17. #include "slip.h"
  18. #include "ax25.h"
  19. #include "netrom.h"
  20. #include "nr4.h"
  21. #include "socket.h"
  22. #include "trace.h"
  23. #include "ip.h"
  24. #include "commands.h"
  25.  
  26. static int near nr_aliasck __ARGS((char *alias));
  27. static int near accept_bc __ARGS((char *addr,unsigned ifnum));
  28. static struct nr_bind * near find_best __ARGS((struct nr_bind *list,unsigned obso));
  29. static struct nr_bind * near find_binding __ARGS((struct nr_bind *list,struct nrnbr_tab *neighbor));
  30. static struct nrnbr_tab * near find_nrnbr __ARGS((char *, unsigned));
  31. static struct nrnf_tab * near find_nrnf __ARGS((char *, unsigned));
  32. static struct nr_bind * near find_worst __ARGS((struct nr_bind *list));
  33. #ifdef    XXX
  34. static char *nr_getroute __ARGS((char *));
  35. #endif
  36. static struct raw_nr *Raw_nr;
  37.  
  38. struct nriface Nrifaces[NRNUMIFACE];
  39. unsigned Nr_numiface = 0;
  40. struct nrnbr_tab *Nrnbr_tab[NRNUMCHAINS];
  41. struct nrroute_tab *Nrroute_tab[NRNUMCHAINS];
  42. struct nrnf_tab *Nrnf_tab[NRNUMCHAINS];
  43.  
  44. unsigned Nr_nfmode                 = NRNF_NOFILTER;
  45. unsigned short Nr_ttl             = 15;
  46. static unsigned Obso_init         = 6;
  47. static unsigned Obso_minbc         = 5;
  48. static unsigned Nr_maxroutes     = 5;
  49. unsigned Nr_autofloor             = 10;
  50. int Nr_verbose     = 0;
  51. int Nr_derate     = 1;        /* Allow automatic derating of routes */
  52. int Nr_promisc     = 0;        /* behave promisuously with nr bcasts or not? */
  53.  
  54. struct iface *Nr_iface = NULLIF;
  55.  
  56. /* send a NET/ROM layer 3 datagram */
  57. void
  58. nr3output(char *dest,struct mbuf *data)
  59. {
  60.     struct nr3hdr n3hdr;
  61.     struct mbuf *n3b;
  62.  
  63.     memcpy(n3hdr.dest,dest,AXALEN);    /* copy destination field */
  64.     n3hdr.ttl = Nr_ttl;                /* time to live from initializer parm */
  65.  
  66.     if((n3b = htonnr3(&n3hdr)) == NULLBUF){
  67.         free_p(data);
  68.         return;
  69.     }
  70.  
  71.     append(&n3b, data);
  72.  
  73.     /* The null interface indicates that the packet needs to have */
  74.     /* an appropriate source address inserted by nr_route */
  75.     nr_route(n3b,NULLAX25);
  76. }
  77.  
  78. /* send IP datagrams across a net/rom network connection */
  79. int
  80. nr_send(struct mbuf *bp,struct iface *iface,int32 gateway,int prec,int del,int tput,int rel)
  81. {
  82.     struct arp_tab *arp;
  83.  
  84.     if((arp = arp_lookup(ARP_NETROM,gateway)) == NULLARP){
  85.         free_p(bp);    /* drop the packet if no route */
  86.         return -1;
  87.     }
  88.     dump(iface,IF_TRACE_OUT,CL_NETROM,bp);
  89.  
  90.     nr_sendraw(arp->hw_addr, NRPROTO_IP, NRPROTO_IP, bp);
  91.     return 0;
  92. }
  93.  
  94. /* Send arbitrary protocol data on top of a NET/ROM connection */
  95. void
  96. nr_sendraw(char *dest,unsigned family,unsigned proto,struct mbuf *data)
  97. {
  98.     struct mbuf *pbp;
  99.     struct nr4hdr n4hdr;
  100.  
  101.     /* Create a "network extension" transport header */
  102.     n4hdr.opcode = NR4OPPID;
  103.     n4hdr.u.pid.family = family;
  104.     n4hdr.u.pid.proto = proto;
  105.  
  106.     if((pbp = htonnr4(&n4hdr)) == NULLBUF){
  107.         free_p(data);
  108.         return;
  109.     }
  110.     append(&pbp,data);        /* Append the data to that */
  111.     nr3output(dest, pbp); /* and pass off to level 3 code */
  112. }
  113.  
  114. /* Arrange for receipt of raw NET/ROM datagrams */
  115. struct raw_nr *
  116. raw_nr(char protocol)
  117. {
  118.     struct raw_nr *rp = mxallocw(sizeof(struct raw_nr));
  119.  
  120.     rp->protocol = protocol;
  121.     rp->next = Raw_nr;
  122.     if(rp->next != NULLRNR)
  123.         rp->next->prev = rp;
  124.     Raw_nr = rp;
  125.     return rp;
  126. }
  127.  
  128. /* Free a raw NET/ROM descriptor */
  129. void
  130. del_rnr(struct raw_nr *rpp)
  131. {
  132.     struct raw_nr *rp;
  133.  
  134.     /* Do sanity check on arg */
  135.     for(rp = Raw_nr; rp != NULLRNR; rp = rp->next)
  136.         if(rp == rpp)
  137.             break;
  138.  
  139.     if(rp == NULLRNR)
  140.         return;    /* Doesn't exist */
  141.  
  142.     /* Unlink */
  143.     if(rp->prev != NULLRNR)
  144.         rp->prev->next = rp->next;
  145.     else
  146.         Raw_nr = rp->next;
  147.  
  148.     if(rp->next != NULLRNR)
  149.         rp->next->prev = rp->prev;
  150.  
  151.     /* Free resources */
  152.     free_q(&rp->rcvq);
  153.     xfree(rp);
  154. }
  155.  
  156. /* Figure out if a call is assigned to one of my net/rom
  157.  * interfaces.
  158.  */
  159. int
  160. ismyNcall(char *addr)
  161. {
  162.     int i;
  163.  
  164. /* NREX bke 920717 */
  165.     for(i = 0; i < Nr_numiface; i++)
  166.         if(addreq(Nrifaces[i].call,addr))    /* was: [i].iface->hwaddr */
  167.             return (i + 1);
  168. /* bke */
  169.  
  170.     return 0;
  171. }
  172.  
  173. /* Route net/rom network layer packets.
  174.  */
  175. void
  176. nr_route(
  177. struct mbuf *bp,                /* network packet */
  178. struct ax25_cb *iaxp)            /* incoming ax25 control block */
  179. {
  180.     struct nr3hdr n3hdr;
  181.     struct ax25_cb *axp;
  182.     struct mbuf *hbp, *pbp;
  183.     struct raw_nr *rnr;
  184.     struct nrnbr_tab *np;
  185.     struct nrroute_tab *rp;
  186.     struct nr_bind *bindp;
  187.     struct iface *iface;
  188.     struct ip ip;
  189.     char * nrcall;    /* NREX bke 920717 */
  190.  
  191.     if(ntohnr3(&n3hdr,&bp) == -1){
  192.         free_p(bp);
  193.         return;
  194.     }
  195.     /* If this isn't an internally generated network packet,
  196.      * give the router a chance to record a route back to the
  197.      * sender, in case they aren't in the local node's routing
  198.      * table yet.
  199.      */
  200.     if(iaxp != NULLAX25){
  201.         unsigned ifnum;
  202.  
  203.         /* find the interface number */
  204.         for(ifnum = 0; ifnum < Nr_numiface; ifnum++)
  205.             if(iaxp->iface == Nrifaces[ifnum].iface)
  206.                 break;
  207.  
  208.         if(ifnum == Nr_numiface){    /* Not a net/rom interface! */
  209.             free_p(bp);
  210.             return;
  211.         }
  212.         /* Add (possibly) a zero-quality recorded route via */
  213.         /* the neighbor from which this packet was received */
  214.         /* Note that this doesn't work with digipeated neighbors. */
  215.         nr_routeadd("######",n3hdr.source,ifnum,0,iaxp->path,0,1);  /* NREX bke 920809 */
  216.     }
  217.  
  218.     /* A packet from me, to me, can only be one thing:
  219.      * a horrible routing loop.  This will probably result
  220.      * from a bad manual ARP entry, but we should fix these
  221.      * obscure errors as we find them.
  222.      */
  223.     if(ismyNcall(n3hdr.dest)){
  224.         struct nr4hdr n4hdr;
  225.  
  226.         /* Toss if from me, or if we can't read the header */
  227.         if(iaxp == NULLAX25 || ntohnr4(&n4hdr,&bp) == -1){
  228.             free_p(bp);
  229.         } else if((n4hdr.opcode & NR4OPCODE) == NR4OPPID){
  230.             for(rnr = Raw_nr; rnr != NULLRNR; rnr = rnr->next){
  231.                 if(rnr->protocol != n4hdr.u.pid.family ||
  232.                   rnr->protocol != n4hdr.u.pid.proto)
  233.                     continue;
  234.  
  235.                 /* Duplicate the data portion, and put the
  236.                  * level 3 header back on */
  237.                 dup_p(&pbp,bp,0,len_p(bp));
  238.  
  239.                 if(pbp != NULLBUF && (hbp = htonnr3(&n3hdr)) != NULLBUF){
  240.                     append(&hbp,pbp);
  241.                     enqueue(&rnr->rcvq,hbp);
  242.                 } else {
  243.                     free_p(pbp);
  244.                     free_p(hbp);
  245.                 }
  246.             }
  247.             /* IP does not use a NET/ROM level 3 socket */
  248.             if(n4hdr.u.pid.family == NRPROTO_IP
  249.               && n4hdr.u.pid.proto == NRPROTO_IP) {
  250.                 struct arp_tab *arp;
  251.  
  252.                 dup_p(&pbp,bp,0,len_p(bp));
  253.                 ntohip(&ip,&pbp);
  254.                 free_p(pbp);
  255.                 if((arp = arp_add(ip.source,ARP_NETROM,n3hdr.source,0,0)) != NULLARP) {
  256.                     stop_timer(&arp->timer);
  257.                     set_timer(&arp->timer,0L);
  258.                 }
  259.                 ip_route(iaxp->iface,Nr_iface,bp,0);
  260.             } else {        /* we don't do this proto */
  261.                 free_p(bp);
  262.             }
  263.         } else {
  264.             /* Must be net/rom transport: */
  265.             nr4input(&n4hdr,bp);
  266.         }
  267.         return;
  268.     }
  269.  
  270. /* L3RT bke 920712 920809 L3RTT-answer */
  271.     if (addreq(n3hdr.dest,Ax25multi[10]) && iaxp) {
  272.         if (n3hdr.ttl-1) {                /* TTL  n o t  over? */
  273.             /* route back to origin! */
  274.             if ((rp = find_nrroute(n3hdr.source)) == NULLNRRTAB) {
  275.                 /* can't happen, but who knows? */
  276.                 free_p(bp);
  277.                 return;
  278.             }
  279.  
  280.             /* don't bother other neighbours even if they have a better */
  281.             /* quality to the sender of the L3RTT frame                 */
  282.             bindp = rp->routes;
  283.             while (bindp && !addreq(bindp->via->call, n3hdr.source))
  284.                 bindp = bindp->next;
  285.  
  286.             if (!bindp) {
  287.                 free_p(bp);
  288.                 return;
  289.             }
  290.         } else {
  291.             free_p(bp);
  292.             return;
  293.         }
  294.     } else {
  295.         if((rp = find_nrroute(n3hdr.dest)) == NULLNRRTAB) {
  296.             /* no route, drop the packet */
  297.             free_p(bp);
  298.             return;
  299.         }
  300.         if((bindp = find_best(rp->routes,1)) == NULLNRBIND) {
  301.             /* This shouldn't happen yet, but might if we add */
  302.             /* dead route detection */
  303.             free_p(bp);
  304.             return;
  305.         }
  306.     }
  307.     /* bke */
  308.  
  309.     np = bindp->via;
  310.     iface = Nrifaces[np->iface].iface;
  311.     nrcall = Nrifaces[np->iface].call; /* NREX bke 920717 address of Net/ROM call */
  312.  
  313.     /* Now check to see if iaxp is null.  That is a signal that the packet
  314.      * originates here, so we need to insert the callsign of the appropriate
  315.      * interface
  316.      */
  317.  
  318.     /* NREX bke 920717 changed iface->hwaddr to nrcall */
  319.     if(iaxp == NULLAX25)
  320.         memcpy(n3hdr.source,nrcall,AXALEN);
  321.     /* bke */
  322.  
  323.     if(--n3hdr.ttl == 0) {         /* the packet's time to live is over! */
  324.         free_p(bp);
  325.         return;
  326.     }
  327.  
  328.     /* Make sure there is a connection to the neighbor */
  329.     /* NREX bke 920717 the same as above: use nrcall, not hwaddr */
  330.  
  331.     if((axp = find_ax25(np->call,nrcall)) == NULLAX25 ||
  332.         axp->state != CONNECTED){
  333.         /* Open a new connection or reinitialize old one */
  334.         /* hwaddr has been advanced to point to neighbor + digis */
  335.         if((axp = open_ax25(iface,nrcall,np->call, AX_ACTIVE,
  336.           s_arcall, s_atcall, s_ascall,-1)) == NULLAX25) {
  337.             free_p(bp);
  338.             return;
  339.         }
  340.         axp->user = 0;
  341.     }
  342.  
  343.     /* now format network header */
  344.     if((pbp = htonnr3(&n3hdr)) == NULLBUF){
  345.         free_p(bp);
  346.         return;
  347.     }
  348.     append(&pbp,bp);        /* append data to header */
  349.  
  350.     /* put AX.25 PID on front */
  351.     bp = pushdown(pbp,1);
  352.     bp->data[0] = PID_NETROM;
  353.  
  354.     if((pbp = segmenter(bp,iface->flags->paclen)) == NULLBUF){
  355.         free_p(bp);
  356.         return;
  357.     }
  358.     send_ax25(axp,pbp,DGRAM);    /* pass it off to ax25 code */
  359. }
  360.  
  361. /*
  362.  * Validate the alias field is good quality ascii to prevent network corruption
  363.  */
  364. static int near
  365. nr_aliasck(char *alias)
  366. {
  367.     int c, x = ALEN;
  368.  
  369.     while (x--) {
  370.         c = *alias++;
  371.         if (!isprint( (int) c) )
  372.             return 1;
  373.     }
  374.     return 0;
  375. }
  376.  
  377. /* Perform a nodes broadcast on interface # ifno in the net/rom
  378.  * interface table.
  379.  */
  380. void
  381. nr_bcnodes(unsigned ifno,char *dest)
  382. {
  383.     struct mbuf *dbp, *savehdr;
  384.     struct nrroute_tab *rp;
  385.     struct nrnbr_tab *np;
  386.     struct nr_bind * bp;
  387.     struct nr3dest nrdest;
  388.     int i, didsend = 0, numdest = 0;
  389.     char *cp;
  390.     struct iface *axif = Nrifaces[ifno].iface;
  391.     char   *nrcall     = Nrifaces[ifno].call;    /* NREX bke 920717 */
  392.  
  393.     /* prepare the header */
  394.     struct mbuf *hbp = alloc_mbuf(NR3NODEHL);
  395.  
  396.     hbp->cnt = NR3NODEHL;
  397.  
  398.     *hbp->data = NR3NODESIG;
  399.     memcpy(hbp->data+1,Nrifaces[ifno].alias,ALEN);
  400.  
  401.     /* Some people don't want to advertise any routes; they
  402.      * just want to be a terminal node.  In that case we just
  403.      * want to send our call and alias and be done with it.
  404.      */
  405.     if(!Nr_verbose){
  406.         (*axif->output)(axif,dest,nrcall,PID_NETROM,hbp);   /* NREX bke 920717 */
  407.         return;
  408.     }
  409.  
  410.     /* make a copy of the header in case we need to send more than */
  411.     /* one packet */
  412.     savehdr = copy_p(hbp,NR3NODEHL);
  413.  
  414.     /* now scan through the routing table, finding the best routes */
  415.     /* and their neighbors.  create destination subpackets and append */
  416.     /* them to the header */
  417.     for(i = 0; i < NRNUMCHAINS; i++){
  418.         for(rp = Nrroute_tab[i]; rp != NULLNRRTAB; rp = rp->next){
  419.             /* look for best, non-obsolescent route */
  420.             if((bp = find_best(rp->routes,0)) == NULLNRBIND)
  421.                 continue;    /* no non-obsolescent routes found */
  422.  
  423.             if(bp->quality == 0)            /* this is a loopback route */
  424.                 continue;                    /* we never broadcast these */
  425.  
  426.             if (bp->quality < Nr_autofloor)    /* below threshhold route */
  427.                 continue ;                    /* so don't broadcast it */
  428.  
  429.             if (rp->alias[0] == '#')        /* NREX bke 920809 hidden node? */
  430.                 continue ;                     /* forget it. */
  431.  
  432.             if (nr_aliasck(rp->alias))        /* corrupted alias entry? */
  433.                 continue ;                    /* don't rebroadcast it */
  434.                                             /* safety measure! */
  435.             np = bp->via;
  436.             /* insert best neighbor */
  437.             memcpy(nrdest.neighbor,np->call,AXALEN);
  438.             /* insert destination from route table */
  439.             memcpy(nrdest.dest,rp->call,AXALEN);
  440.             /* insert alias from route table */
  441.             strcpy(nrdest.alias,rp->alias);
  442.             /* insert quality from binding */
  443.             nrdest.quality = bp->quality;
  444.             /* create a network format destination subpacket */
  445.             if((dbp = htonnrdest(&nrdest)) == NULLBUF){
  446.                 free_p(hbp);                /* drop the whole idea ... */
  447.                 free_p(savehdr);
  448.                 return;
  449.             }
  450.             /* we now have a partially filled packet */
  451.             didsend = 0;
  452.             append(&hbp,dbp);                /* append to header and others */
  453.             /* see if we have appended as many destinations
  454.              * as we can fit into a single broadcast.  If we
  455.              * have, go ahead and send them out.
  456.              */
  457.             if(++numdest == NRDESTPERPACK){    /* filled it up */
  458.                 /* indicate that we did broadcast */
  459.                 didsend = 1;
  460.                 /* reset the destination counter */
  461.                 numdest = 0;
  462.                 (*axif->output)(axif,dest,nrcall,PID_NETROM,hbp);
  463.                 /* new header */
  464.                 hbp = copy_p(savehdr,NR3NODEHL);
  465.             }
  466.         }
  467.     }
  468.  
  469.     /* Now, here is something totally weird.  If our interfaces */
  470.     /* have different callsigns than this one, advertise a very */
  471.     /* high quality route to them.  Is this a good idea?  I don't */
  472.     /* know.  However, it allows us to simulate a bunch of net/roms */
  473.     /* hooked together with a diode matrix coupler. */
  474.     for(i = 0; i < Nr_numiface; i++){
  475.         if(i == ifno)
  476.             continue;        /* don't bother with ours */
  477.         cp = Nrifaces[i].call;    /* NREX bke 920717 */
  478.         if(!addreq((char *)axif->hwaddr,cp)){
  479.             /* both destination and neighbor address */
  480.             memcpy(nrdest.dest,cp,AXALEN);
  481.             memcpy(nrdest.neighbor,cp,AXALEN);
  482.             /* alias of the interface */
  483.             strcpy(nrdest.alias,Nrifaces[i].alias);
  484.             /* and the very highest quality */
  485.             nrdest.quality = 255;
  486.             /* create a network format destination subpacket */
  487.             if((dbp = htonnrdest(&nrdest)) == NULLBUF){
  488.                 free_p(hbp);    /* drop the whole idea ... */
  489.                 free_p(savehdr);
  490.                 return;
  491.             }
  492.             /* we now have a partially filled packet */
  493.             didsend = 0;
  494.             /* append to header and others */
  495.             append(&hbp,dbp);
  496.             if(++numdest == NRDESTPERPACK){    /* filled it up */
  497.                 /* indicate that we did broadcast */
  498.                 didsend = 1;
  499.                 /* reset the destination counter */
  500.                 numdest = 0;
  501.                 (*axif->output)(axif,dest,nrcall,PID_NETROM,hbp); /* send it *//* NREX bke 920717 */
  502.                 /* new header */
  503.                 hbp = copy_p(savehdr,NR3NODEHL);
  504.             }
  505.         }
  506.     }
  507.  
  508.     /* If we have a partly filled packet left over, or we never */
  509.     /* sent one at all, we broadcast: */
  510.  
  511.     if(!didsend || numdest > 0)
  512.         (*axif->output)(axif, dest, nrcall,PID_NETROM, hbp); /* NREX bke 920717 */
  513.     else {
  514.         if(numdest == 0)     /* free the header copies */
  515.             free_p(hbp);
  516.     }
  517.  
  518.     free_p(savehdr);
  519. }
  520.  
  521. /* attach the net/rom interface.  no parms for now. */
  522. int
  523. nr_attach(int argc,char *argv[],void *p)
  524. {
  525.     if(Nr_iface != NULLIF) {
  526.         tprintf(Ifexist,"netrom");
  527.         return -1;
  528.     }
  529.  
  530.     Nr_iface = mxallocw(sizeof(struct iface));
  531.     Nr_iface->addr = Ip_addr;
  532.  
  533.     /* The strxdup is needed to keep the detach routine happy (it'll
  534.      * free the allocated memory)
  535.      */
  536.     Nr_iface->name = strxdup("netrom");
  537.  
  538.     if(Nr_iface->hwaddr == NULLCHAR)
  539.         Nr_iface->hwaddr = strxdup(Mycall);
  540.  
  541.     Nr_iface->mtu = NR4MAXINFO;
  542.     setencap(Nr_iface,"NETROM");
  543.     Nr_iface->next = Ifaces;
  544.     Nr_iface->niface = 255;        /* used for routing - DB3FL */
  545.     Ifaces = Nr_iface;
  546.     memcpy(Nr4user,Mycall,AXALEN);
  547.     return 0;
  548. }
  549.  
  550. /* This function checks an ax.25 address and interface number against
  551.  * the filter table and mode, and returns -1 if the address is to be accepted
  552.  * verbatim, the quality if filtered in or 0 if it is to be filtered out.
  553.  */
  554. static int near
  555. accept_bc(char *addr,unsigned ifnum)
  556. {
  557.     struct nrnf_tab *fp = find_nrnf(addr,ifnum);    /* look it up */
  558.  
  559.     if(Nr_nfmode == NRNF_NOFILTER)        /* no filtering in effect */
  560.         return -1;
  561.  
  562.     if (fp != NULLNRNFTAB && Nr_nfmode == NRNF_ACCEPT)
  563.         return fp->quality ;
  564.  
  565.     if (fp == NULLNRNFTAB && Nr_nfmode == NRNF_REJECT)
  566.         return -1;
  567.  
  568.     return (Nr_promisc) ? -1 : 0;
  569. }
  570.  
  571. /* receive and process node broadcasts. */
  572. void
  573. nr_nodercv(struct iface *iface,char *source,struct mbuf *bp)
  574. {
  575.     int ifnum, qual;
  576.     char bcalias[AXALEN];
  577.     struct nr3dest ds;
  578.  
  579.     /* First, see if this is even a net/rom interface: */
  580.     for(ifnum = 0; ifnum < Nr_numiface; ifnum++)
  581.         if(iface == Nrifaces[ifnum].iface)
  582.             break;
  583.  
  584.     if(ifnum == Nr_numiface){    /* not in the interface table */
  585.         free_p(bp);
  586.         return;
  587.     }
  588.  
  589.     if ((qual = accept_bc(source,ifnum)) == 0) {    /* check against filter */
  590.         free_p(bp) ;                                /* and get quality */
  591.         return ;
  592.     }
  593.  
  594.     /* See if it has a routing broadcast signature: */
  595.     if(PULLCHAR(&bp) != NR3NODESIG){
  596.         free_p(bp);
  597.         return;
  598.     }
  599.  
  600.     /* now try to get the alias */
  601.     if(pullup(&bp,bcalias,ALEN) < ALEN){
  602.         free_p(bp);
  603.         return;
  604.     }
  605.  
  606.     /* now check that the alias field is not corrupted - saftey measure! */
  607.     if (nr_aliasck(bcalias)) {
  608.         free_p(bp);
  609.         return;
  610.     }
  611.  
  612.     bcalias[ALEN] = '\0';        /* null terminate */
  613.  
  614.     /* enter the neighbor into our routing table */
  615.     if(qual == -1)
  616.         qual = Nrifaces[ifnum].quality;    /* use default quality */
  617.  
  618.     if(nr_routeadd(bcalias, source, ifnum, qual, source, 0, 0) == -1){
  619.         free_p(bp);
  620.         return;
  621.     }
  622.  
  623.     /* we've digested the header; now digest the actual */
  624.     /* routing information */
  625.     while(ntohnrdest(&ds,&bp) != -1){
  626.  
  627.         /* ignore routes to me! */
  628.         if(ismyNcall(ds.dest))
  629.             continue;
  630.  
  631.         /* ignore routes with corrupted aliases - safety measure */
  632.         if (nr_aliasck (ds.alias))
  633.             continue;
  634.  
  635.         /* ignore loopback paths to ourselves */
  636.         if(ismyNcall(ds.neighbor))
  637.             continue;
  638.         else
  639.             ds.quality = ((ds.quality * qual + 128) / 256) & 0xff;
  640.  
  641.         /* ignore routes below the minimum quality threshhold */
  642.         if(ds.quality < Nr_autofloor)
  643.             continue;
  644.  
  645.         if(nr_routeadd(ds.alias,ds.dest,ifnum,ds.quality,source,0,0) == -1)
  646.             break;
  647.     }
  648.     free_p(bp);    /* This will free the mbuf if anything fails above */
  649. }
  650.  
  651.  
  652. /* The following are utilities for manipulating the routing table */
  653.  
  654. /* hash function for callsigns.  Look familiar? */
  655. int16
  656. nrhash(char *s)
  657. {
  658.     char x = 0;
  659.     int i;
  660.  
  661.     for(i = ALEN; i !=0; i--)
  662.         x ^= *s++ & 0xfe;
  663.     x ^= *s & SSID;
  664.     return (int16)(uchar(x) % NRNUMCHAINS);
  665. }
  666.  
  667. /* Find a neighbor table entry.  Neighbors are determined by
  668.  * their callsign and the interface number.  This takes care
  669.  * of the case where the same switch or hosts uses the same
  670.  * callsign on two different channels.  This isn't done by
  671.  * net/rom, but it might be done by stations running *our*
  672.  * software.
  673.  */
  674. static struct nrnbr_tab * near
  675. find_nrnbr(char *addr,unsigned ifnum)
  676. {
  677.     struct nrnbr_tab *np;
  678.     int16 hashval = nrhash(addr);
  679.  
  680.     /* search hash chain */
  681.     for(np = Nrnbr_tab[hashval]; np != NULLNTAB; np = np->next){
  682.         /* convert first in  list to ax25 address format */
  683.         if(addreq(np->call,addr) && np->iface == ifnum){
  684.             return np;
  685.         }
  686.     }
  687.     return NULLNTAB;
  688. }
  689.  
  690.  
  691. /* Find a route table entry */
  692. struct nrroute_tab *
  693. find_nrroute(char *addr)
  694. {
  695.     struct nrroute_tab *rp;
  696.  
  697.     /* Find appropriate hash chain */
  698.     int16 hashval = nrhash(addr);
  699.  
  700.     /* search hash chain */
  701.     for(rp = Nrroute_tab[hashval]; rp != NULLNRRTAB; rp = rp->next){
  702.         if(addreq(rp->call,addr)){
  703.             return rp;
  704.         }
  705.     }
  706.     return NULLNRRTAB;
  707. }
  708.  
  709. /* Try to find the AX.25 address of a node with the given alias.  Return */
  710. /* a pointer to the AX.25 address if found, otherwise NULLCHAR.  The alias */
  711. /* should be a six character, blank-padded, upper-case string. */
  712.  
  713. char *
  714. find_nralias(char *alias)
  715. {
  716.     int i;
  717.     struct nrroute_tab *rp;
  718.  
  719.     /* Since the route entries are hashed by ax.25 address, we'll */
  720.     /* have to search all the chains */
  721.  
  722.     for(i = 0; i < NRNUMCHAINS; i++)
  723.         for(rp = Nrroute_tab[i]; rp != NULLNRRTAB; rp = rp->next)
  724.             if(strncmp(alias, rp->alias, 6) == 0)
  725.                 return rp->call;
  726.  
  727.     /* If we get to here, we're out of luck */
  728.     return NULLCHAR;
  729. }
  730.  
  731.  
  732. /* Find a binding in a list by its neighbor structure's address */
  733. static struct nr_bind * near
  734. find_binding(struct nr_bind *list,struct nrnbr_tab *neighbor)
  735. {
  736.     struct nr_bind *bp;
  737.  
  738.     for(bp = list; bp != NULLNRBIND; bp = bp->next)
  739.         if(bp->via == neighbor)
  740.             return bp;
  741.  
  742.     return NULLNRBIND;
  743. }
  744.  
  745. /* Find the worst quality non-permanent binding in a list */
  746. static
  747. struct nr_bind * near
  748. find_worst(struct nr_bind *list)
  749. {
  750.     struct nr_bind *bp, *worst = NULLNRBIND;
  751.     unsigned minqual = 1000;    /* infinity */
  752.  
  753.     for(bp = list; bp != NULLNRBIND; bp = bp->next)
  754.         if(!(bp->flags & NRB_PERMANENT) && bp->quality < minqual){
  755.             worst = bp;
  756.             minqual = bp->quality;
  757.         }
  758.  
  759.     return worst;
  760. }
  761.  
  762. /* Find the best binding of any sort in a list.  If obso is 1,
  763.  * include entries below the obsolescence threshhold in the
  764.  * search (used when this is called for routing broadcasts).
  765.  * If it is 0, routes below the threshhold are treated as
  766.  * though they don't exist.
  767.  */
  768. static
  769. struct nr_bind * near
  770. find_best(struct nr_bind *list,unsigned obso)
  771. {
  772.     struct nr_bind *bp, *best = NULLNRBIND;
  773.     int maxqual = -1;    /* negative infinity */
  774.  
  775.     for(bp = list; bp != NULLNRBIND; bp = bp->next)
  776.         if((int)bp->quality > maxqual)
  777.             if(obso || bp->obsocnt >= Obso_minbc){
  778.                 best = bp;
  779.                 maxqual = bp->quality;
  780.             }
  781.  
  782.     return best;
  783. }
  784.  
  785. /* Add a route to the net/rom routing table */
  786. int
  787. nr_routeadd(
  788. char *alias,            /* net/rom node alias, blank-padded and */
  789.                         /* null-terminated */
  790. char *dest,                /* destination node callsign */
  791. unsigned ifnum,            /* net/rom interface number */
  792. unsigned quality,        /* route quality */
  793. char *neighbor,            /* neighbor node + 2 digis (max) in arp format */
  794. unsigned permanent,        /* 1 if route is permanent (hand-entered) */
  795. unsigned record)        /* 1 if route is a "record route" */
  796. {
  797.     struct nrroute_tab *rp;
  798.     struct nr_bind *bp;
  799.     struct nrnbr_tab *np;
  800.     int16 rhash, nhash;
  801.  
  802.     /* See if a routing table entry exists for this destination */
  803.     if((rp = find_nrroute(dest)) == NULLNRRTAB){
  804.         rp = mxallocw(sizeof(struct nrroute_tab));
  805.         /* create a new route table entry */
  806.         sprintf(rp->alias,"%.6s",alias);
  807.         addrcp(rp->call,dest);
  808.         rhash = nrhash(dest);
  809.         rp->next = Nrroute_tab[rhash];
  810.         if(rp->next != NULLNRRTAB)
  811.             rp->next->prev = rp;
  812.         Nrroute_tab[rhash] = rp;    /* link at head of hash chain */
  813.     } else if(permanent || !strncmp(rp->alias,"##temp",6)) {
  814.         sprintf(rp->alias,"%.6s",alias); /* update the alias */
  815.     }
  816.  
  817.     /* See if an entry exists for this neighbor */
  818.     if((np = find_nrnbr(neighbor,ifnum)) == NULLNTAB){
  819.         np = mxallocw(sizeof(struct nrnbr_tab));
  820.         /* create a new neighbor entry */
  821.         memcpy(np->call,neighbor,AXALEN);
  822.         np->iface = ifnum;
  823.         nhash = nrhash(neighbor);
  824.         np->next = Nrnbr_tab[nhash];
  825.         if(np->next != NULLNTAB)
  826.             np->next->prev = np;
  827.         Nrnbr_tab[nhash] = np;
  828.     } else if(permanent){        /* force this path to the neighbor */
  829.         memcpy(np->call,neighbor,AXALEN);
  830.     }
  831.  
  832.     /* See if there is a binding between the dest and neighbor */
  833.     if((bp = find_binding(rp->routes,np)) == NULLNRBIND){
  834.         bp = mxallocw(sizeof(struct nr_bind));
  835.         /* create a new binding and link it in */
  836.         bp->via = np;    /* goes via this neighbor */
  837.         bp->next = rp->routes;    /* link into binding chain */
  838.         if(bp->next != NULLNRBIND)
  839.             bp->next->prev = bp;
  840.         rp->routes = bp;
  841.         rp->num_routes++;    /* bump route count */
  842.         np->refcnt++;        /* bump neighbor ref count */
  843.         bp->quality = quality;
  844.         bp->obsocnt = Obso_init;    /* use initial value */
  845.         if(permanent)
  846.             bp->flags |= NRB_PERMANENT;
  847.         else if(record)    /* notice permanent overrides record! */
  848.             bp->flags |= NRB_RECORDED;
  849.     } else {
  850.         if(permanent){    /* permanent request trumps all */
  851.             bp->quality = quality;
  852.             bp->obsocnt = Obso_init;
  853.             bp->flags |= NRB_PERMANENT;
  854.             bp->flags &= ~NRB_RECORDED;    /* perm is not recorded */
  855.         } else if(!(bp->flags & NRB_PERMANENT)){    /* not permanent */
  856.             if(record){    /* came from nr_route */
  857.                 if(bp->flags & NRB_RECORDED){ /* no mod non-rec bindings */
  858.                     bp->quality = quality;
  859.                     bp->obsocnt = Obso_init; /* freshen recorded routes */
  860.                 }
  861.             } else {        /* came from a routing broadcast */
  862.                 bp->quality = quality;
  863.                 bp->obsocnt = Obso_init;
  864.                 bp->flags &= ~NRB_RECORDED; /* no longer a recorded route */
  865.             }
  866.         }
  867.     }
  868.  
  869.     /* Now, check to see if we have too many bindings, and drop */
  870.     /* the worst if we do */
  871.     if(rp->num_routes > Nr_maxroutes){
  872.         /* since find_worst never returns permanent entries, the */
  873.         /* limitation on number of routes is circumvented for    */
  874.         /* permanent routes */
  875.         if((bp = find_worst(rp->routes)) != NULLNRBIND){
  876.             nr_routedrop(dest,bp->via->call,bp->via->iface);
  877.         }
  878.     }
  879.  
  880.     return 0;
  881. }
  882.  
  883.  
  884. /* Drop a route to dest via neighbor */
  885. int
  886. nr_routedrop(char *dest,char *neighbor,unsigned ifnum)
  887. {
  888.     struct nrroute_tab *rp;
  889.     struct nrnbr_tab *np;
  890.     struct nr_bind *bp;
  891.  
  892.     if((rp = find_nrroute(dest)) == NULLNRRTAB)
  893.         return -1;
  894.  
  895.     if((np = find_nrnbr(neighbor,ifnum)) == NULLNTAB)
  896.         return -1;
  897.  
  898.     if((bp = find_binding(rp->routes,np)) == NULLNRBIND)
  899.         return -1;
  900.  
  901.     /* drop the binding first */
  902.     if(bp->next != NULLNRBIND)
  903.         bp->next->prev = bp->prev;
  904.     if(bp->prev != NULLNRBIND)
  905.         bp->prev->next = bp->next;
  906.     else
  907.         rp->routes = bp->next;
  908.  
  909.     xfree(bp);
  910.     rp->num_routes--;        /* decrement the number of bindings */
  911.     np->refcnt--;            /* and the number of neighbor references */
  912.  
  913.     /* now see if we should drop the route table entry */
  914.     if(rp->num_routes == 0){
  915.         if(rp->next != NULLNRRTAB)
  916.             rp->next->prev = rp->prev;
  917.         if(rp->prev != NULLNRRTAB)
  918.             rp->prev->next = rp->next;
  919.         else
  920.             Nrroute_tab[nrhash(dest)] = rp->next;
  921.  
  922.         xfree(rp);
  923.     }
  924.  
  925.     /* and check to see if this neighbor can be dropped */
  926.     if(np->refcnt == 0){
  927.         if(np->next != NULLNTAB)
  928.             np->next->prev = np->prev;
  929.         if(np->prev != NULLNTAB)
  930.             np->prev->next = np->next;
  931.         else
  932.             Nrnbr_tab[nrhash(neighbor)] = np->next;
  933.  
  934.         xfree(np);
  935.     }
  936.  
  937.     return 0;
  938. }
  939.  
  940. #ifdef    XXX
  941. /* Find the best neighbor for destination dest, in arp format */
  942. static char *
  943. nr_getroute(char *dest)
  944. {
  945.     struct nrroute_tab *rp;
  946.     struct nr_bind *bp;
  947.  
  948.     if((rp = find_nrroute(dest)) == NULLNRRTAB)
  949.         return NULLCHAR;
  950.  
  951.     if((bp = find_best(rp->routes,1)) == NULLNRBIND)    /* shouldn't happen! */
  952.         return NULLCHAR;
  953.  
  954.     return bp->via->call;
  955. }
  956. #endif    /* notused */
  957.  
  958. /* Find an entry in the filter table */
  959. static struct nrnf_tab * near
  960. find_nrnf(char *addr,unsigned ifnum)
  961. {
  962.     struct nrnf_tab *fp;
  963.  
  964.     /* Find appropriate hash chain */
  965.     int16 hashval = nrhash(addr);
  966.  
  967.     /* search hash chain */
  968.     for(fp = Nrnf_tab[hashval]; fp != NULLNRNFTAB; fp = fp->next){
  969.         if(addreq(fp->neighbor,addr) && fp->iface == ifnum){
  970.             return fp;
  971.         }
  972.     }
  973.  
  974.     return NULLNRNFTAB;
  975. }
  976.  
  977. /* Add an entry to the filter table.  Return 0 on success,
  978.  * -1 on failure
  979.  */
  980. int
  981. nr_nfadd(char *addr,unsigned ifnum,unsigned qual)
  982. {
  983.     struct nrnf_tab *fp;
  984.     int16 hashval = nrhash(addr);
  985.  
  986.     if(find_nrnf(addr,ifnum) != NULLNRNFTAB)
  987.         return 0;    /* already there; it's a no-op */
  988.  
  989.     fp = mxallocw(sizeof(struct nrnf_tab));
  990.  
  991.     memcpy(fp->neighbor,addr,AXALEN);
  992.     fp->iface = ifnum;
  993.     fp->next = Nrnf_tab[hashval];
  994.     fp->quality = qual;
  995.     if(fp->next != NULLNRNFTAB)
  996.         fp->next->prev = fp;
  997.     Nrnf_tab[hashval] = fp;
  998.  
  999.     return 0;
  1000. }
  1001.  
  1002. /* Drop a neighbor from the filter table.  Returns 0 on success, -1
  1003.  * on failure.
  1004.  */
  1005. int
  1006. nr_nfdrop(char *addr,unsigned ifnum)
  1007. {
  1008.     struct nrnf_tab *fp;
  1009.  
  1010.     if((fp = find_nrnf(addr,ifnum)) == NULLNRNFTAB)
  1011.         return -1;    /* not in the table */
  1012.  
  1013.     if(fp->next != NULLNRNFTAB)
  1014.         fp->next->prev = fp->prev;
  1015.     if(fp->prev != NULLNRNFTAB)
  1016.         fp->prev->next = fp->next;
  1017.     else
  1018.         Nrnf_tab[nrhash(addr)] = fp->next;
  1019.  
  1020.     xfree(fp);
  1021.  
  1022.     return 0;
  1023. }
  1024.  
  1025. /* called from lapb whenever a link failure implies that a particular ax25
  1026.  * path may not be able to carry netrom traffic too well. Experimental!!!!
  1027.  */
  1028. void
  1029. nr_derate(struct ax25_cb *axp)
  1030. {
  1031.     struct nrnbr_tab *np ;
  1032.     struct nrroute_tab *rp;
  1033.     struct nr_bind *bp;
  1034.     struct mbuf *buf;
  1035.     int i, ifnum, nr_traffic = 0;    /* assume no netrom traffic on connection */
  1036.  
  1037.     /* First, see if the derate funciton is enabled or
  1038.      * this is even a net/rom interface:
  1039.      */
  1040.     if (!Nr_derate || axp == NULLAX25)
  1041.         return;            /* abandon ship! */
  1042.  
  1043.     /* If it is valid for netrom traffic, lets see if there is */
  1044.     /* really netrom traffic on the connection to be derated.  */
  1045.     for (buf = axp->txq; buf != NULLBUF; buf = buf->anext)
  1046.         if ((buf->data[0] & 0xff) == PID_NETROM)
  1047.             nr_traffic = 1;        /* aha - netrom traffic! */
  1048.  
  1049.     if (!nr_traffic)
  1050.         return;        /* no sign of being used by netrom just now */
  1051.  
  1052.     /* find the interface number */
  1053.     for (ifnum = 0 ; ifnum < Nr_numiface ; ifnum++)
  1054.         if (axp->iface == Nrifaces[ifnum].iface)
  1055.             break ;
  1056.  
  1057.     if (ifnum == Nr_numiface)    /* may well happen! */
  1058.         return ;
  1059.  
  1060.     /* we now have the appropriate interface entry */
  1061.     for (i = 0 ; i < NRNUMCHAINS ; i++) {
  1062.         for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) {
  1063.             for (bp = rp->routes ; bp != NULLNRBIND ; bp = bp->next) {
  1064.                 np = bp->via;
  1065.                 if(bp->quality >= 1 && np->iface == ifnum &&
  1066.                 !(bp->flags & NRB_PERMANENT) &&
  1067.                 !memcmp(np->call,axp->path + AXALEN,ALEN) &&
  1068.                 (np->call[6] & SSID) == ((axp->path + AXALEN)[6] & SSID)) {
  1069.                     bp->quality = ((bp->quality * 2) / 3);
  1070.                 }
  1071.             }
  1072.         }
  1073.     }
  1074. }
  1075.  
  1076. #endif /* NETROM */
  1077.